home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 049a / send_100.zip / SENDNET.C next >
C/C++ Source or Header  |  1991-02-16  |  18KB  |  581 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <dir.h>
  6. #include <dos.h>
  7. #include <io.h>
  8. #include <conio.h>
  9. #include <time.h>
  10.  
  11. #define MAX_FILENAME_LENGTH  256
  12. #define MAX_LINE_LENGTH      1024
  13.  
  14. typedef
  15.  struct FIDO_message_attribute_struct
  16.   {
  17.    unsigned                  Private              : 1;
  18.    unsigned                  Crash                : 1;
  19.    unsigned                  Recd                 : 1;
  20.    unsigned                  Sent                 : 1;
  21.    unsigned                  FileAttached         : 1;
  22.    unsigned                  InTransit            : 1;
  23.    unsigned                  Orphan               : 1;
  24.    unsigned                  KillSent             : 1;
  25.    unsigned                  Local                : 1;
  26.    unsigned                  HoldForPickup        : 1;
  27.    unsigned                  Direct               : 1;
  28.    unsigned                  FileRequest          : 1;
  29.    unsigned                  ReturnReceiptRequest : 1;
  30.    unsigned                  IsReturnReceipt      : 1;
  31.    unsigned                  AuditRequest         : 1;
  32.    unsigned                  FileUpdateReq        : 1;
  33.   }                          FIDO_message_attrib_type;
  34.  
  35. typedef
  36.  struct FIDO_message_struct
  37.   {
  38.    char                      fromUserName[36];
  39.    char                      toUserName[36];
  40.    char                      subject[72];
  41.    char                      dateTime[20];
  42.    unsigned                  timesRead;
  43.    unsigned                  destNode;
  44.    unsigned                  origNode;
  45.    unsigned                  cost;
  46.    unsigned                  origNet;
  47.    unsigned                  destNet;
  48.    unsigned                  destZone;
  49.    unsigned                  origZone;
  50.    unsigned                  destPoint;
  51.    unsigned                  origPoint;
  52.    unsigned                  replyTo;
  53.    FIDO_message_attrib_type  Attribute;
  54.    unsigned                  nextReply;
  55.    char                      text[1];
  56.   }                          FIDO_message_type;
  57. typedef
  58.  FIDO_message_type *         FIDO_message_ptr_type;
  59.  
  60. typedef
  61.  struct                      node_list_struct
  62.   {
  63.    struct node_list_struct * next;
  64.    unsigned                  zone;
  65.    unsigned                  net;
  66.    unsigned                  node;
  67.    unsigned                  point;
  68.    char                      name[1];
  69.   }                          node_list_type;
  70.  
  71. typedef node_list_type *     node_list_ptr_type;
  72.  
  73. typedef
  74.  struct                      address_struct
  75.   {
  76.    unsigned                  zone;
  77.    unsigned                  net;
  78.    unsigned                  node;
  79.    unsigned                  point;
  80.    char                      name[1];
  81.   }                          address_type;
  82.  
  83. typedef address_type *       address_ptr_type;
  84.  
  85. void                         add_to_list(char *            buf,
  86.                                          char *            file,
  87.                                          unsigned          line);
  88. void *                       allocate_memory(unsigned      n_bytes);
  89. unsigned                     get_highest_message_number(char *area);
  90. void                         initialize(unsigned           argc,
  91.                                         char *             argv[]);
  92. void                         load_bad_message_table(void);
  93. address_ptr_type             parse_node_address(char *     c,
  94.                                                 char *     file,
  95.                                                 unsigned   line);
  96. void                         parse_parms(unsigned          argc,
  97.                                          char *            argv[]);
  98. void                         process_to_file(char *        file);
  99. void                         send_net_mail(char *          file);
  100. char *                       starts_with(char *            buf,
  101.                                          char *            pat);
  102.  
  103. char                         area[MAX_FILENAME_LENGTH];
  104. struct ffblk                 ff_blk;
  105. unsigned                     message_number;
  106. char *                       month[] = {
  107.                                 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  108.                                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  109. unsigned                     n_clusters;
  110. node_list_ptr_type           to_list;
  111. node_list_ptr_type           to_list_end;
  112.  
  113. void                         main (unsigned                argc,
  114.                                    char *                  argv[])
  115. {
  116.  unsigned                    i;
  117.  initialize(argc, argv);
  118.  for (i=1; i<argc; i++)
  119.   if (strnicmp(argv[i], "-f", 2) == 0)
  120.    send_net_mail(&argv[i][2]);
  121.  exit(0);
  122. }
  123.  
  124. void                         add_to_list(char *            buf,
  125.                                          char *            file,
  126.                                          unsigned          line)
  127. {
  128.  address_ptr_type            address;
  129.  node_list_ptr_type          entry;
  130.  char *                      name;
  131.  if ((name = starts_with(buf, "To:")) == NULL)
  132.   {
  133.    fprintf(stderr, "Error:  Missing \"To\" address on line %u in file \"%s\".\n",
  134.            line, file);
  135.    exit(1);
  136.   };
  137.  address = parse_node_address(name, file, line);
  138.  entry = (node_list_ptr_type) allocate_memory(sizeof(node_list_type) +
  139.                                               strlen(address->name));
  140.  entry->zone  = address->zone;
  141.  entry->net   = address->net;
  142.  entry->node  = address->node;
  143.  entry->point = address->point;
  144.  strcpy(entry->name, address->name);
  145.  free(address);
  146.  if (to_list_end == NULL)
  147.    to_list     =
  148.    to_list_end = entry;
  149.   else
  150.    {
  151.     to_list_end->next = entry;
  152.     to_list_end = entry;
  153.    };
  154.  return;
  155. }
  156.  
  157. void *                       allocate_memory(unsigned      n_bytes)
  158. {
  159.  void *                      buffer;
  160.  if ((buffer = malloc(n_bytes)) == NULL)
  161.   {
  162.    fprintf(stderr, "Error:  Out of memory.\n");
  163.    exit(1);
  164.   };
  165.  memset(buffer, 0, n_bytes);
  166.  return(buffer);
  167. }
  168.  
  169. unsigned                     get_highest_message_number(char *area)
  170. {
  171.  unsigned                    done;
  172.  char                        file[MAX_FILENAME_LENGTH];
  173.  unsigned                    highest_message_number;
  174.  unsigned                    i;
  175.  strcpy(file, area);
  176.  strcat(file, "*.msg");
  177.  highest_message_number = 0u;
  178.  done = findfirst(file, &ff_blk, FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC);
  179.  while (!done)
  180.   {
  181.    *strrchr(ff_blk.ff_name, '.') = '\000';
  182.    i = atoi(ff_blk.ff_name);
  183.    if (i > highest_message_number)
  184.     highest_message_number = i;
  185.    done = findnext(&ff_blk);
  186.   };
  187.  return(highest_message_number+1u);
  188. }
  189.  
  190. void                         initialize(unsigned           argc,
  191.                                         char *             argv[])
  192. {
  193.  to_list     =
  194.  to_list_end = NULL;
  195.  strcpy(area,"");
  196.  if (argc < 2u)
  197.   {
  198.    fprintf(stderr, "\n\n\n\n\n");
  199.    fprintf(stderr, "Function:  SendNet sends NetMail to lists of recepients.\n");
  200.    fprintf(stderr, "\n");
  201.    fprintf(stderr, "Usage:  SendNet -a<NetDir> -f<MsgFile>...\n");
  202.    fprintf(stderr, "        Where:  <NetDir> is the NetMail directory.\n");
  203.    fprintf(stderr, "                <MsgFile> is a file containing the message to be sent.\n");
  204.    fprintf(stderr, "\n");
  205.    fprintf(stderr, "Each message file has the following line format.\n");
  206.    fprintf(stderr, "    To:  <name> @ <address> ---+\n");
  207.    fprintf(stderr, "    . . . . .                  | At least one recepient must\n");
  208.    fprintf(stderr, "    To:  <name> @ <address>    | be specified.  The To and @To\n");
  209.    fprintf(stderr, "    [@To:  <to_list_file>]     | lines may be in any order.\n");
  210.    fprintf(stderr, "    . . . . .                  |\n");
  211.    fprintf(stderr, "    [@To:  <to_list_file>]  ---+\n");
  212.    fprintf(stderr, "    From: <name> @ <address>\n");
  213.    fprintf(stderr, "   [Subject: <subject text>]\n");
  214.    fprintf(stderr, "   [Attribute: [Audit] [Crash | Direct | Hold] [KillSent] [Receipt]]\n");
  215.    fprintf(stderr, "   [@Include: <file where message text is continued]\n");
  216.    fprintf(stderr, "    <message text>\n");
  217.    fprintf(stderr, "    . . . . .\n");
  218.    fprintf(stderr, "    <message text>\n");
  219.    fprintf(stderr, "Note:  Blank lines must separate paragraphs.\n");
  220.    exit(1);
  221.   };
  222.  fprintf(stderr, "Send NetMail Utility.  Written by David Troendle (1:396/5).\n");
  223.  fprintf(stderr, "Tested, documented and distributed by John Souvestre (1:396/1).\n");
  224.  fprintf(stderr, "Version 1.00, February 12, 1991.\n");
  225.  fprintf(stderr, "\n");
  226.  parse_parms(argc, argv);
  227.  message_number = get_highest_message_number(area);
  228.  return;
  229. }
  230.  
  231. address_ptr_type             parse_node_address(char *     c,
  232.                                                 char *     file,
  233.                                                 unsigned   line)
  234. {
  235.  address_ptr_type            address;
  236.  char                        ch;
  237.  char *                      name;
  238.  char *                      node;
  239.  if ((node = strchr(c, '@')) == NULL)
  240.   {
  241.    fprintf(stderr, "Error:  Missing network address on line %u in file \"%s\".\n",
  242.            line, file);
  243.    exit(1);
  244.   };
  245.  name = c;
  246.  c = node++;
  247.  *c = ' ';
  248.  while (*c == ' ')
  249.   c--;
  250.  *++c = '\000';
  251.  address = (address_ptr_type) allocate_memory(sizeof(address_type) +
  252.                                              strlen(name));
  253.  strcpy(address->name, name);
  254.  while (*node == ' ')
  255.   node++;
  256.  c = node;
  257.  while (isdigit(*c))
  258.   c++;
  259.  if (*c == ':')
  260.   {
  261.    *c++ = '\000';
  262.    address->zone = atoi(node);
  263.    node = c;
  264.    while (isdigit(*c))
  265.     c++;
  266.   };
  267.  if (*c == '/')
  268.    {
  269.     *c++ = '\000';
  270.     address->net = atoi(node);
  271.     node = c;
  272.     while (isdigit(*c))
  273.      c++;
  274.    }
  275.   else
  276.    {
  277.     fprintf(stderr, "Error:  Invalid network address on line %u in file \"%s\".\n",
  278.             line, file);
  279.     exit(1);
  280.    };
  281.  ch = *c;
  282.  *c++ = '\000';
  283.  address->node = atoi(node);
  284.  if (ch == '.')
  285.   {
  286.    node = c;
  287.    while (isdigit(*c))
  288.     c++;
  289.    address->point = atoi(node);
  290.   };
  291.  return(address);
  292. }
  293.  
  294. void                         parse_parms(unsigned          argc,
  295.                                          char *            argv[])
  296. {
  297.  unsigned                    i;
  298.  for (i=1; i<argc; i++)
  299.   {
  300.    if (strnicmp(argv[i], "-a", 2) == 0)
  301.     {
  302.      if (strlen(area) > 0)
  303.       {
  304.        fprintf(stderr, "Error:  \"-a\" switch can only appear once.\n");
  305.        exit(1);
  306.       };
  307.      strcpy(area, &argv[i][2]);
  308.      continue;
  309.     };
  310.    if (strnicmp(argv[i], "-f", 2) == 0)
  311.     continue;
  312.    fprintf(stderr, "Error:  Unknown switch: \"%s\".\n", argv[i]);
  313.    exit(1);
  314.   };
  315.  if (strlen(area) == 0)
  316.   {
  317.    fprintf(stderr, "Error:  \"-a\" switch missing or null.\n");
  318.    exit(1);
  319.   };
  320.  if (area[strlen(area) - 1] != '\\')
  321.   strcat(area, "\\");
  322.  return;
  323. }
  324.  
  325. void                         process_to_file(char *        file)
  326. {
  327.  char                        buf[MAX_LINE_LENGTH];
  328.  FILE *                      infile;
  329.  unsigned                    line;
  330.  if ((infile = fopen(file, "r")) == NULL)
  331.   {
  332.    fprintf(stderr, "Error:  Could not open \"To\" file:  \"%s\".\n", file);
  333.    exit(1);
  334.   };
  335.  line = 0u;
  336.  while (fgets(buf, MAX_LINE_LENGTH, infile))
  337.   {
  338.    line++;
  339.    if (strlen(buf) == 1)
  340.     continue;
  341.    add_to_list(buf, file, line);
  342.   };
  343.  fclose(infile);
  344.  return;
  345. }
  346.  
  347. void                         send_net_mail(char *          file)
  348. {
  349.  address_ptr_type            address;
  350.  char                        buf[MAX_LINE_LENGTH];
  351.  char *                      c;
  352.  node_list_ptr_type          entry;
  353.  unsigned                    eof;
  354.  unsigned                    first_line;
  355.  char                        fn[MAX_FILENAME_LENGTH];
  356.  FILE *                      infile;
  357.  unsigned                    len;
  358.  unsigned                    line;
  359.  char *                      mp;
  360.  FIDO_message_ptr_type       msg;
  361.  unsigned                    n_bytes;
  362.  char *                      name;
  363.  FILE *                      outfile;
  364.  char                        outfile_name[MAX_FILENAME_LENGTH];
  365.  struct tm *                 tblock;
  366.  time_t                      timer;
  367.  msg = (FIDO_message_ptr_type) allocate_memory(65530u);
  368.  strcpy(fn, file);
  369.  if ((infile = fopen(fn, "r")) == NULL)
  370.   {
  371.    fprintf(stderr, "Error:  Could not open message file \"%s\".\n", fn);
  372.    exit(1);
  373.   };
  374.  memset(msg, 0, 65530u);
  375.  n_bytes = sizeof(FIDO_message_type) - 1u;
  376.  mp = msg->text;
  377.  line = 0u;
  378.  eof = fgets(buf, MAX_LINE_LENGTH, infile) == NULL;
  379.  if (!eof)
  380.   line++;
  381.  while (!eof)
  382.   {
  383.    if ((c = starts_with(buf, "@To:")) != NULL)
  384.      {
  385.       buf[strlen(buf)-1] = '\000';
  386.       process_to_file(c);
  387.      }
  388.     else
  389.      {
  390.       if ((c = starts_with(buf, "To:")) != NULL)
  391.          add_to_list(buf, file, line);
  392.        else
  393.         break;
  394.      };
  395.    eof = fgets(buf, MAX_LINE_LENGTH, infile) == NULL;
  396.    if (!eof)
  397.     line++;
  398.   };
  399.  
  400.  if ((name = starts_with(buf, "From:")) == NULL)
  401.   {
  402.    fprintf(stderr, "Error:  Missing \"From\" address on line %u in file \"%s\".\n",
  403.            line, fn);
  404.    exit(1);
  405.   };
  406.  address = parse_node_address(name, fn, line);
  407.  memset(msg->fromUserName, 0, 36);
  408.  strncpy(msg->fromUserName, address->name, 35);
  409.  msg->origZone  = address->zone;
  410.  msg->origNet   = address->net;
  411.  msg->origNode  = address->node;
  412.  msg->origPoint = address->point;
  413.  free(address);
  414.  eof = fgets(buf, MAX_LINE_LENGTH, infile) == NULL;
  415.  if (!eof)
  416.   line++;
  417.  
  418.  if (!eof && ((name = starts_with(buf, "subject:")) != NULL))
  419.    {
  420.     while (*name == ' ')
  421.      name++;
  422.     if ((c = strrchr(buf, '\n')) != NULL)
  423.      *c = '\000';
  424.     memset(msg->subject, 0, 72);
  425.     strncpy(msg->subject, name, 71);
  426.     eof = fgets(buf, MAX_LINE_LENGTH, infile) == NULL;
  427.     if (!eof)
  428.      line++;
  429.    }
  430.   else
  431.    {
  432.     strcpy(msg->subject, "Message generated by SendNet");
  433.    };
  434.  if (!eof && ((name = starts_with(buf, "attribute:")) != NULL))
  435.   {
  436.    strlwr(buf);
  437.    if (strstr(buf, "audit"))
  438.     msg->Attribute.AuditRequest = 1u;
  439.    if (strstr(buf, "crash"))
  440.     msg->Attribute.Crash = 1u;
  441.    if (strstr(buf, "Direct"))
  442.     msg->Attribute.Direct = 1u;
  443.    if (strstr(buf, "hold"))
  444.     msg->Attribute.HoldForPickup = 1u;
  445.    if (strstr(buf, "killsent"))
  446.     msg->Attribute.KillSent = 1u;
  447.    if (strstr(buf, "receipt"))
  448.     msg->Attribute.ReturnReceiptRequest = 1u;
  449.  
  450.    if ((msg->Attribute.Crash +
  451.         msg->Attribute.Direct +
  452.         msg->Attribute.HoldForPickup) > 1)
  453.     {
  454.      fprintf(stderr, "Error:  Conflict between Crash/Direct/Hold on line %u in file \"%s\".\n",
  455.              line, fn);
  456.      exit(1);
  457.     };
  458.    eof = fgets(buf, MAX_LINE_LENGTH, infile) == NULL;
  459.    if (!eof)
  460.     line++;
  461.   };
  462.  msg->Attribute.Local   = 1u;
  463.  msg->Attribute.Private = 1u;
  464.  
  465.  if (!eof && ((name = starts_with(buf, "@include:")) != NULL))
  466.   {
  467.    while (*name == ' ')
  468.     name++;
  469.    fclose(infile);
  470.    if ((c = strrchr(name, '\n')) != NULL)
  471.     *c = '\000';
  472.    if (strlen(name) >= MAX_FILENAME_LENGTH)
  473.     {
  474.      fprintf(stderr, "Error:  Invalid include file name \"%s\" on line %u in file \"%s\".\n",
  475.              name, line, fn);
  476.      exit(1);
  477.     };
  478.    strcpy(fn, name);
  479.    if ((infile = fopen(fn, "r")) == NULL)
  480.     {
  481.      fprintf(stderr, "Error:  Could not open include file \"%s\".\n", fn);
  482.      exit(1);
  483.     };
  484.    line = 0u;
  485.    eof = fgets(buf, MAX_LINE_LENGTH, infile) == NULL;
  486.    if (!eof)
  487.     line++;
  488.   };
  489.  
  490.  first_line = 1u;
  491.  while (!eof)
  492.   {
  493.    if ((c = strrchr(buf, '\n')) == NULL)
  494.     {
  495.      fprintf(stderr, "Error:  Message line too long on line %u in file \"%s\".\n",
  496.              line, fn);
  497.      exit(1);
  498.     };
  499.    *c = '\r' | 0x80;
  500.    if ((len = strlen(buf)) == 1)
  501.     *c &= 0x7f;
  502.    if ((len == 1) && !first_line)
  503.     *(mp-1) &= 0x7f;
  504.    if ((*(mp-1) == ((char) 0x8d)) && !first_line)
  505.     {
  506.      *(mp-1) = ' ';
  507.      *mp++   = 0x8d;
  508.      n_bytes++;
  509.     };
  510.    first_line = 0u;
  511.    if (n_bytes > (65530u - len))
  512.     {
  513.      fprintf(stderr, "Error:  Message too long on line %u in file \"%s\".\n",
  514.              line, fn);
  515.      exit(1);
  516.     };
  517.    strcat(mp, buf);
  518.    mp      += len;
  519.    n_bytes += len;
  520.    eof = fgets(buf, MAX_LINE_LENGTH, infile) == NULL;
  521.    if (!eof)
  522.     line++;
  523.   };
  524.  fclose(infile);
  525.  
  526.  for (entry = to_list; entry; entry = entry->next)
  527.   {
  528.    sprintf(outfile_name, "%s%u.Msg", area, message_number++);
  529.    memset(msg->toUserName, 0, 36);
  530.    strncpy(msg->toUserName, entry->name, 35);
  531.    msg->destZone          = entry->zone;
  532.    msg->destNet           = entry->net;
  533.    msg->destNode          = entry->node;
  534.    msg->destPoint         = entry->point;
  535.    timer = time(NULL);
  536.    tblock = localtime(&timer);
  537.    sprintf(msg->dateTime, "%02u %3s %02u  %02u:%02u:%02u",
  538.            tblock->tm_mday,
  539.            month[tblock->tm_mon],
  540.            tblock->tm_year,
  541.            tblock->tm_hour,
  542.            tblock->tm_min,
  543.            tblock->tm_sec);
  544.    if ((outfile = fopen(outfile_name, "wb")) == NULL)
  545.     {
  546.      fprintf(stderr, "Error:  Could not open \"%s\" for output.\n", outfile_name);
  547.      exit(1);
  548.     };
  549.    fwrite(msg, n_bytes, 1, outfile);
  550.    fclose(outfile);
  551.    printf("File \"%s\" sent to %s at ", file, msg->toUserName);
  552.    if (msg->destZone)
  553.     printf("%u:", msg->destZone);
  554.    printf("%u/%u", msg->destNet, msg->destNode);
  555.    if (msg->destPoint)
  556.     printf(".%u", msg->destPoint);
  557.    printf("\n     in message %s\n", outfile_name);
  558.   };
  559.  free(msg);
  560.  return;
  561. }
  562.  
  563. char *                       starts_with(char *            buf,
  564.                                          char *            pat)
  565. {
  566.  char *                      c;
  567.  unsigned                    len;
  568.  c   = buf;
  569.  len = strlen(pat);
  570.  while (*c == ' ')
  571.   c++;
  572.  if (strnicmp(c, pat, len) == 0)
  573.    {
  574.     c += len;
  575.     while (*c == ' ')
  576.      c++;
  577.     return(c);
  578.    }
  579.   else
  580.    return(NULL);
  581. }